#ifndef __RTC_STREAM_H
#define __RTC_STREAM_H
#include <string>
#include <memory>
#include <rtc_base/rtc_certificate.h>
#include <rtc_base/third_party/sigslot/sigslot.h>
#include "base/event_loop.h"
#include "pc/peer_connection.h"
#include "stream/rtc_packet.h"
namespace xrtc
{
    class RtcStream;
    enum class RtcStreamType
    {

        kPush,
        kPull,

    };
    class RtcStreamListener
    {
    public:
        virtual void OnConnectionState(RtcStream *stream, PeerConnectionState state) = 0;
        // transport
        virtual void OnRtpPacketReceived(RtcStream *stream, const char *data, size_t len) = 0;
        virtual void OnRtcpPacketReceived(RtcStream *stream, const char *data, size_t len) = 0;
        // live
        virtual void OnRtpPacket(RtcStream *stream, webrtc::MediaType media_type, std::shared_ptr<RtcPacket> packet) = 0;
        virtual void OnStreamException(RtcStream *stream) = 0;
        virtual void OnSrInfo(RtcStream *stream, webrtc::MediaType media_type, uint32_t rtp_timestamp,
                              webrtc::NtpTime ntp) = 0;
        virtual void OnNackReceived(RtcStream *, webrtc::MediaType media_type, const std::vector<uint16_t> &nack_list) = 0;
    };
    class RtcStream : public sigslot::has_slots<>
    {

    public:
        RtcStream(EventLoop *el, PortAllocator *allocator, uint64_t uid, const std::string &stream_name,
                  bool audio, bool video, uint32_t log_id);
        virtual ~RtcStream();
        virtual std::string CreateOffer() = 0;
        virtual RtcStreamType StreamType() = 0;
        int Start(rtc::RTCCertificate *certificate);
        int SetRemoteSdp(const std::string &sdp);
        void RegisterListener(RtcStreamListener *listener)
        {
            listener_ = listener;
        }
        uint64_t GetUid() { return uid; }
        const std::string &GetStreamName() { return stream_name; }
        bool IsTransparent() const { return pc->IsTransparent(); }
        bool IsLive() const { return pc->IsLive(); }
        void set_mode(const std::string &mode) { pc->set_mode(mode); }
        std::string ToString();
        int SendRtp(const char *data, size_t len);
        int SendRtcp(const char *data, size_t len);
        PeerConnectionState state() const { return state_; };

    private:
        void OnConnectionState(PeerConnection *, PeerConnectionState state);
        void OnRtpPacketReceived(PeerConnection *, rtc::CopyOnWriteBuffer *packet, int64_t ts);
        void OnRtcpPacketReceived(PeerConnection *, rtc::CopyOnWriteBuffer *packet, int64_t ts);
        void OnSrInfo(PeerConnection *, webrtc::MediaType media_type, uint32_t rtp_timestamp, webrtc::NtpTime ntp);

    protected:
        EventLoop *el;
        uint64_t uid;
        std::string stream_name;
        bool audio;
        bool video;
        uint32_t log_id;
        PeerConnection *pc = nullptr;
        RtcStreamListener *listener_ = nullptr;

    private:
        friend class RtcStreamManager;
        friend void IceTimeoutCb(EventLoop *el, TimerWatcher *w, void *data);
        PeerConnectionState state_ = PeerConnectionState::kNew;
        TimerWatcher *ice_timeout_watcher_ = nullptr;
    };

} // namespace xrtc

#endif